﻿/*************************************************************************************
 * 工    具：  HK_BezierLineRenderer
 * 
 * 描    述：  HK_BezierLineRenderer 用于在 Unity 场景中生成并渲染三次贝塞尔曲线的组件，需配合LineRenderer使用。
 *            支持通过调整端点位置、控制柄旋转/长度、曲线分段数等参数动态控制曲线形状，
 *            支持世界坐标/局部坐标绘制模式，且支持编辑时（Editor）和运行时（Runtime）自动更新。
 * 
 * 版    本：  V1.0
 * 作    者：  京产肠饭
 * 
 * 创    建：  2025/06/07  V1.0
 *            
 * 链    接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using UnityEngine;

namespace HKTools
{
    [ExecuteAlways]
    [RequireComponent(typeof(LineRenderer))]
    public class HK_BezierLineRenderer : MonoBehaviour
    {
        [Header("曲线端点")]
        public Vector3 startPoint = Vector3.left * 3.5f;
        public Vector3 endPoint = Vector3.right * 3.5f;

        [Header("控制柄设置")]
        public Quaternion startControlRotation = Quaternion.identity;
        public Quaternion endControlRotation = Quaternion.identity;
        [Range(0f, 20f)]
        public float startHandleLength = 2.5f;
        [Range(0f, 20f)]
        public float endHandleLength = 2.5f;

        [Header("曲线分段数")]
        [Range(2, 256)]
        public int segmentCount = 24;

        [Header("是否在世界坐标系下绘制")]
        public bool isWorldSpace = false;

        private LineRenderer lineRenderer;

        void Awake()
        {
            lineRenderer = GetComponent<LineRenderer>();
            UpdateBezierCurve();
        }

#if UNITY_EDITOR
        void OnValidate()
        {
            // 运行时不执行验证（避免影响性能）
            if (Application.isPlaying) return;
            // 确保LineRenderer引用存在（编辑时可能被手动删除）
            if (lineRenderer == null) lineRenderer = GetComponent<LineRenderer>();
            UpdateBezierCurve();
        }
#endif

        /// <summary>
        /// 更新贝塞尔曲线的顶点数据，驱动LineRenderer渲染
        /// </summary>
        public void UpdateBezierCurve()
        {
            // 初始化/校验LineRenderer组件（防止被手动移除）
            if (lineRenderer == null)
            {
                lineRenderer = GetComponent<LineRenderer>();
                if (lineRenderer == null) lineRenderer = gameObject.AddComponent<LineRenderer>();
            }

            // 计算端点世界坐标（根据坐标空间转换）
            Vector3 startWorldPos = isWorldSpace ? startPoint : transform.TransformPoint(startPoint);
            Vector3 endWorldPos = isWorldSpace ? endPoint : transform.TransformPoint(endPoint);

            // 计算控制柄方向（考虑坐标空间的基础旋转）
            Quaternion baseRotation = isWorldSpace ? transform.rotation : Quaternion.identity;
            Vector3 startControlDir = (baseRotation * startControlRotation) * Vector3.forward;
            Vector3 endControlDir = (baseRotation * endControlRotation) * Vector3.forward;

            // 计算控制柄实际位置
            Vector3 controlPoint1 = startWorldPos + startControlDir * startHandleLength;
            Vector3 controlPoint2 = endWorldPos + endControlDir * endHandleLength;

            // 配置LineRenderer并生成曲线顶点
            lineRenderer.useWorldSpace = isWorldSpace;
            lineRenderer.positionCount = segmentCount + 1;
            for (int i = 0; i <= segmentCount; i++)
            {
                float t = i / (float)segmentCount;
                Vector3 curvePoint = CalculateCubicBezier(t, startWorldPos, controlPoint1, controlPoint2, endWorldPos);
                lineRenderer.SetPosition(i, isWorldSpace ? curvePoint : transform.InverseTransformPoint(curvePoint));
            }
        }

        /// <summary>
        /// 计算三次贝塞尔曲线在参数t处的具体坐标
        /// </summary>
        Vector3 CalculateCubicBezier(float t, Vector3 start, Vector3 control1, Vector3 control2, Vector3 end)
        {
            float u = 1f - t;
            return u * u * u * start
                 + 3f * u * u * t * control1
                 + 3f * u * t * t * control2
                 + t * t * t * end;
        }
    }
}